package grpc

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"io"
	"learning/gooop/grpc/logger"
	"learning/gooop/grpc/pb"
	"net"
	"strconv"
)

type HelloServer int

func (me *HelloServer) SimpleRequest(ctx context.Context, msg *pb.HelloMessage) (*pb.HelloMessage, error) {
	//logger.Logf("HelloServer.SimpleRequest, %s", msg.Msg)
	msg.Msg = "reply " + msg.Msg
	return msg, nil
}

func (me *HelloServer) ClientStream(stream pb.HelloServer_ClientStreamServer) error {
	for {
		msg, err := stream.Recv()
		if err == io.EOF {
			logger.Logf("HelloServer.ClientStream, EOF")
			break
		}

		if err != nil {
			logger.Logf("HelloServer.ClientStream, err=%v", err)
			return err
		}

		logger.Logf("HelloServer.ClientStream, recv %s", msg.Msg)
	}

	err := stream.SendAndClose(&pb.HelloMessage{
		Msg: "reply ClientStream",
	})
	if err != nil {
		logger.Logf("HelloServer.ClientStream, SendAndClose err=%v", err)
	}
	return nil
}

func (me *HelloServer) ServerStream(msg *pb.HelloMessage, stream pb.HelloServer_ServerStreamServer) error {
	iMsgCount, err := strconv.Atoi(msg.Msg)
	if err != nil {
		return err
	}

	for i := 0; i < iMsgCount; i++ {
		msg := &pb.HelloMessage{
			Msg: fmt.Sprintf("ServerStream-%08d", i),
		}
		err := stream.Send(msg)
		if err != nil {
			return err
		}
	}

	return nil
}

func (me *HelloServer) DualStream(stream pb.HelloServer_DualStreamServer) error {
	for {
		msg, err := stream.Recv()
		if err == io.EOF {
			return nil
		}

		if err != nil {
			logger.Logf("HelloServer.DualStream, recv err=%v", err)
			return err
		}
		logger.Logf("HelloServer.DualStream, recv msg=%v", msg.Msg)

		ret := &pb.HelloMessage{
			Msg: "reply " + msg.Msg,
		}
		err = stream.Send(ret)
		if err != nil {
			logger.Logf("HelloServer.DualStream, send err=%v", err)
			return err
		}
	}
}

func (me *HelloServer) BeginServeTCP(port int) error {
	listener, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port))
	if err != nil {
		return err
	}

	server := grpc.NewServer()
	pb.RegisterHelloServerServer(server, me)
	go func() {
		panic(server.Serve(listener))
	}()

	return nil
}
